#ifndef INTERPRETER_H
#define INTERPRETER_H

#include "unified.h"
#include "scope.h"

void register_builtin(scope_t *scope,
  char *name_string, value_t *(*function)(generic_list_t*,scope_t*,int,handler_t*),
  int arity, int varargs);

void throw_exception(handler_t *handler, char *tag_string, char *value_string);

inline value_t *tail_call(scope_t *scope, call_t *call, int tail, handler_t *handler);
int interpret(function_t*f,int argc, char **argv);

generic_list_t*evaluate_list(scope_t *scope, generic_list_t *list, handler_t *handler);
value_t *evaluate_item(scope_t *scope, value_t *item, handler_t *handler);
value_t *evaluate_call(scope_t *scope, call_t *call, int tail, handler_t *handler);
value_t *call_closure(closure_t *closure, generic_list_t *arguments, int tail, scope_t **save, handler_t *handler);

UChar *show_value(value_t *value);

scope_t *construct_builtins();

scope_t *make_scope(scope_t *parent, generic_list_t *name_list, generic_list_t *value_list, name_t *tail);
char *from_unicode(UChar *u_string);
UChar *to_unicode(char *char_string);
void show_exception(handler_t*handler);
value_t *run_closure(closure_t *closure, handler_t *handler);
#endif // INTERPRETER_H
